package com.handyshop.mall.auth.config.redis;

import com.handyshop.mall.auth.config.AuthClientDetailsService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;

import javax.sql.DataSource;

/**
 * redis token实现
 *
 * @author handy
 * @date 2020/11/12 15:16
 */
@RequiredArgsConstructor
public class OAuth2RedisConfig extends AuthorizationServerConfigurerAdapter {
    private final UserDetailsService userDetailsService;
    private final AuthenticationManager authenticationManager;
    private final DataSource dataSource;
    private final TokenStore redisTokenStore;
    private final TokenEnhancer jwtTokenEnhancer;

    /**
     * redis token 方式
     */
    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
        // 支持 password 模式
        endpoints.authenticationManager(authenticationManager)
                .tokenStore(redisTokenStore)
                // 配置JWT的内容增强器
                .tokenEnhancer(jwtTokenEnhancer)
                // 配置加载用户信息的服务
                .userDetailsService(userDetailsService);
    }

    /**
     * 限制客户端访问认证接口的权限。
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        // 允许客户端访问 OAuth2 授权接口，否则请求 token 会返回 401。
        security.allowFormAuthenticationForClients();
        // 允许已授权用户访问 checkToken 接口
        security.checkTokenAccess("isAuthenticated()");
        // 允许已授权用户获取 token 接口。
        security.tokenKeyAccess("isAuthenticated()");
    }

    /**
     * 查询数据库模式
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(new AuthClientDetailsService(dataSource));
    }

}